#include "maincontrol.h"

MainControl::MainControl(QObject *parent) : QObject(parent)
{
    //读取存储配置
    m_videoConfigs = m_config.loadVideoConfigs();
    m_allFileSavePath = m_config.loadDataSavePath();

    //短消息存储（主线程中实现）
    m_saveMsg = new SaveMsg(m_config.loadMsgIni());
}

MainControl::~MainControl()
{
    stopThread();
    if(m_saveMsg) {
        delete m_saveMsg;
    }
    //m_config.saveVideoConfigs(m_videoConfigs);        //没涉及到更改，就暂时取消保存操作了
    //m_config.saveDataSavePath(m_allFileSavePath);
    //m_config.saveGroupIP(m_groupIP);
    //m_config.saveNetName(m_netName);
}

//step 2
void MainControl::initThread()
{
    for(int i = 0; i < m_videoConfigs.size(); i++) {

        //创建存储对象，开始存储
        QThread *m_thread = new QThread;
        SaveBase *m_saveObj;

        //根据不同配置创建不同的存储对象
        switch (m_videoConfigs[i].saveMethod) {
        case _air:  //空中h264
            m_saveObj = new SaveH264();
            break;
        case _airMidWaveifd:  //空中中波红外Raw
             m_saveObj = new SaveAirWV();
            break;
        case _groundMidWaveifd: //地面中波红外Raw
            m_saveObj = new SaveGroundLongWV(640, 512);
            break;
        case _groundLongWaveifd: //地面长波红外Raw
            m_saveObj = new SaveGroundLongWV(320, 256);
            break;
        case _QXMsg: //黑体_气象站_能见度仪信息
            m_saveObj = new SaveGroundLongWV(320, 256);
            break;
        case _TYFSMsg: //太阳辐射计信息
            m_saveObj = new SaveGroundLongWV(320, 256);
            break;
        case _GNSSMsg: //GNSS信息
            m_saveObj = new SaveGroundLongWV(320, 256);
            break;
        default: //其他的暂时不加入，后面会加入head中枚举的SaveIndex的其他类型
            m_saveObj = new SaveBase();
            break;
        }

        m_saveObj->moveToThread(m_thread);

        m_saveThreads.append(m_saveObj);

        m_threads.append(m_thread);

        //创建udp对象，开始采集
        MyUdpReceive *udpRecieve = new MyUdpReceive(m_videoConfigs[i]);
        m_udps.append(udpRecieve);

        //连接udp采集数据到存储数据
        connect(udpRecieve, &MyUdpReceive::sigToSaveData, m_saveObj, &SaveBase::onWorking);

        //测试，将图片放到控件上显示
        connect(m_saveObj, &SaveBase::sigToShowImg, this, &MainControl::sigToShowImg);

        connect(m_thread, &QThread::started, m_saveObj, &SaveBase::onInitTimer);

        //连接磁盘满信号，发送给上位机磁盘满了
        connect(m_saveObj, &SaveBase::sigAllDiskFull, this, &MainControl::sigAllDiskFull);
    }
}

//step3
void MainControl::startThread()
{
    //最外层创建的文件夹，以时间命名
    for(int i = 0; i < m_threads.size(); i++) {
        QString dateFileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss");
        m_saveThreads[i]->setInfo(m_videoConfigs[i], dateFileName, m_allFileSavePath);
        m_saveThreads[i]->setSaveStatus(true);
        m_threads[i]->start();
    }

    //发送cameralink开始指令  (已废弃，cameralink已更改，不需要再主动发送指令)
    //MyUdpReceive::sendStatus(true, "192.168.2.5", 2234, "192.168.2.3", 1234);
}

//step 4
void MainControl::stopThread()
{
    for(auto thread : m_threads) {
        if(thread) {
            thread->quit();
            thread->wait();
            thread->deleteLater();
            thread = nullptr;
        }
    }
    m_threads.clear();

    //发送cameralink停止指令 (已废弃，cameralink已更改，不需要再主动发送指令)
    //MyUdpReceive::sendStatus(false, "192.168.2.5", 2234, "192.168.2.3", 1234);

    for(int i = 0; i < m_udps.size(); i++) {
        if(m_udps[i]) {
            delete m_udps[i];
            m_udps[i] = nullptr;
        }
    }
    m_udps.clear();

    for(auto savefileThread : m_saveThreads) {
        if(savefileThread) {
            delete savefileThread;
            savefileThread = nullptr;
        }
    }
    m_saveThreads.clear();
}

void MainControl::startOneThread(int index)
{
    //设置开始状态
    if(m_saveThreads.size() > index) {
        m_saveThreads[index]->setSaveStatus(true);
    } else {
        qDebug() << "设置线程允许存储状态失败，越界访问了";
    }
}
//还行
void MainControl::stopOneThread(int index)
{
    //设置停止状态
    if(m_saveThreads.size() > index) {
        m_saveThreads[index]->setSaveStatus(false);
    } else {
        qDebug() << "设置线程禁止存储状态失败，越界访问了";
    }
}

QStringList MainControl::getAllFileSavePath()
{
    return m_allFileSavePath;
}

void MainControl::onStartStoring(CameraMethod method)
{
    qDebug() << "CameraMethed cmd:" << method;
    switch (method) {
        case MidWaveInfrared: {
            qDebug() << "开始中波红外存储:" << method;
            startOneThread(_groundMidWaveifd);
            emit sigStartStoringResp(method);
            break;
        }
        case LongWaveInfrared: {
            qDebug() << "开始长波红外存储:" << method;
            startOneThread(_groundLongWaveifd);
            emit sigStartStoringResp(method);
            break;
        }
        case aerial: {
            qDebug() << "开始画中画空中相机存储:" << method;
            startOneThread(_air);
            emit sigStartStoringResp(method);
            break;
        }
        case airMidWaveInfraed: {
            qDebug() << "开始空中红外相机存储:" << method;
            startOneThread(_airMidWaveifd);
            emit sigStartStoringResp(method);
            break;
        }
        default:
            break;
    }
}

void MainControl::onStopStoring(CameraMethod method)
{
    switch (method) {
        case MidWaveInfrared: {
            qDebug() << "停止中波红外存储:" << method;
            stopOneThread(_groundMidWaveifd);  //index序号暂未定
            emit sigStopStoringResp(method);
            break;
        }
        case LongWaveInfrared: {
            qDebug() << "停止长波红外存储:" << method;
            stopOneThread(_groundLongWaveifd);
            emit sigStopStoringResp(method);
            break;
        }
        case aerial: {
            qDebug() << "停止空中相机存储:" << method;
            startOneThread(_air);
            emit sigStopStoringResp(method);
           break;
        }
        case airMidWaveInfraed: {
            qDebug() << "停止空中相机存储:" << method;
            startOneThread(_airMidWaveifd);
            emit sigStopStoringResp(method);
           break;
        }
        default:
            break;
    }
}

//查询存储状态
void MainControl::onQueryStatus()
{
    bool midWaveIR = false;
    bool longWaveIR = false;
    bool airMidWaveIR = false;
    bool airvisible = false;
    if(m_saveThreads.size() > 3) {
        midWaveIR = m_saveThreads[2]->getSaveStatus();
        longWaveIR = m_saveThreads[3]->getSaveStatus();
        airMidWaveIR = m_saveThreads[1]->getSaveStatus();
        airvisible = m_saveThreads[0]->getSaveStatus();
    }

    emit sigQueryStatusResp(midWaveIR, longWaveIR, airMidWaveIR, airvisible);
}

//查询视频名称
void MainControl::onQueryVideo()
{
    //windows下模拟数据，实际上用m_allFileSavePath
    QStringList m_diskPaths = {"C:/Users/delos/Desktop/disk1", "C:/Users/delos/Desktop/disk2",
                   "C:/Users/delos/Desktop/disk3", "C:/Users/delos/Desktop/disk4"};

    QStringList sendPaths = {}; //要发送出去的所有文件路径
    int totalFiles = 0; //总文件数
    foreach (const QString &directory, m_diskPaths) {
        QDir dir(directory);
        if(!dir.exists()) {
            qWarning() << "目录不存在,跳过";
            continue;
        }

        //创建目录迭代器
        QDirIterator it(directory, QDir::Files, QDirIterator::Subdirectories);
        int fileCount = 0;

        //遍历目录中的所有文件
        while(it.hasNext()) {
            QString filePath = it.next();
            qDebug() << " " << filePath;
            sendPaths.append(filePath);
            fileCount++;
        }

        qDebug() << "找到文件数:" << fileCount;
        totalFiles += fileCount;

    }
    qDebug() << "总目录数" << m_diskPaths.size();
    qDebug() << "总文件数" << totalFiles;
    for(auto sendPath : sendPaths) {
        qDebug() << sendPath;
    }

    emit sigQueryVideoResp(sendPaths);
}

//删除视频
void MainControl::onDeleteVideo(QString path)
{
    //这里有个问题，如果删除失败，协议中没有设定回复内容
    if(QFile::exists(path)) {
        if(QFile::remove(path)) {
            emit sigDeleteVideoResp(path);
        }
    }
    //emit sigDeleteVideoResp(path);  //这里应该回复删除失败，但是现在没这个关键字节信息，暂时以删除成功代替
}


#ifdef Q_OS_WIN
#include <windows.h>
#else
#include <sys/time.h>
#endif

//授时
void MainControl::onTiming(QDateTime dataTime)
{
    //windows和unix分别授时
    QDateTime utc = dataTime.toUTC();

#ifdef Q_OS_WIN
    //windows系统授时
    SYSTEMTIME st;
    st.wYear = utc.date().year();
    st.wMonth = utc.date().month();
    st.wDay = utc.date().day();
    st.wHour = utc.time().hour();
    st.wMinute = utc.time().minute();
    st.wSecond = utc.time().second();
    st.wMilliseconds = utc.time().msec();

    if(SetSystemTime(&st)) {
        qDebug() << "授时成功";
        emit sigTimingResp();
    } else {
        qDebug() << "授时失败";
    }

#else
    //linux系统授时
    struct timeval tv;
    tv.tv_sec = utc.toSecsSinceEpoch();
    tv.tv_usec = utc.time().msec() * 1000;

    if(settimeofday(&tv, nullptr) == 0) {
        qDebug() << "授时成功";
        emit sigTimingResp();
    } else {
        qDebug() << "授时失败";
    }
#endif
}

//更改h264文件保存时长
void MainControl::onChangeH264Time(quint8 time)
{
    qDebug() << "更改h264文件时长为" << QString::number(time, 10) << "mins";
}
